package com.molichuxing.service.impl;

import com.molichuxing.constants.RedisConstants;
import com.molichuxing.framework.utils.RedisUtil;
import com.molichuxing.service.MileageMonitoringService;
import com.molichuxing.services.business.service.CarsMileageMonitoringBizService;
import com.molichuxing.services.infrastructure.dto.request.create.CarsMileageMonitoringEnterpriseDto;
import com.molichuxing.services.infrastructure.dto.response.CarsMileageMonitoringEnterpriseResDto;
import com.molichuxing.services.infrastructure.dto.response.EnterpriseCarDto;
import com.molichuxing.services.infrastructure.dto.response.OrderEnterpriseDto;
import com.molichuxing.services.infrastructure.service.EnterpriseCarService;
import com.molichuxing.services.infrastructure.service.ICarsMileageMonitoringEnterpriseService;
import com.molichuxing.services.infrastructure.service.IovCarService;
import com.molichuxing.services.infrastructure.service.OrderEnterpriseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 里程监控
 * The type Mileage monitoring service.
 *
 * @author wanghualin
 * @date 2020 -06-10 15:53:22
 */
@Service
@Slf4j
public class MileageMonitoringServiceImpl implements MileageMonitoringService {
    @Autowired
    private IovCarService iovCarService;
    @Autowired
    private EnterpriseCarService enterpriseCarService;
    @Autowired
    private OrderEnterpriseService enterpriseService;
    @Autowired
    private CarsMileageMonitoringBizService carsMileageMonitoringBizService;
    @Autowired
    private ICarsMileageMonitoringEnterpriseService monitoringEnterpriseService;
    @Resource
    private RedisUtil redisUtil;
    /**
     * 小于等于28 号当月处理，大于28号 月一号处理
     */
    private static int DAY_OF_MONTHS_CRITICAL = 28;


    @Override
    public void generateMileageMonitoring(LocalDate localDate) {
        generateMonitoring(localDate);
    }

    /**
     * 生成报警
     *
     * @param localDate
     */
    public void generateMonitoring(LocalDate localDate) {
        List<Integer> dayOfMonths = getDayOfMonths(localDate);
        if (CollectionUtils.isEmpty(dayOfMonths)) {
            return;
        }

        //得到已交车的订单
        List<OrderEnterpriseDto> orderList = enterpriseService.listOrderEnterpriseByDay(dayOfMonths, localDate);
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        /**
         * 得到orderCode
         */
        List<Long> orderCodeList = orderList.stream().map(OrderEnterpriseDto::getOrderCode).collect(Collectors.toList());
        /**
         * 得到租赁中的车辆
         */
        List<EnterpriseCarDto> list = enterpriseCarService.listEnterpriseCar(orderCodeList);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        Map<Long, EnterpriseCarDto> collect = list.stream().
                collect(Collectors.toMap(EnterpriseCarDto::getOrderCode, enterpriseCarDto -> enterpriseCarDto));

        //获取车辆车架号
        List<String> vinList = list.stream().map(EnterpriseCarDto::getVin).collect(Collectors.toList());
        Map<String, Integer> currentMileage;
        try {
            currentMileage = iovCarService.getOdoMileage(vinList);
        } catch (Exception e) {
            log.info("获取车联网实际里程失败-入参：{}", vinList);
            return;
        }

        //生成报警
        for (OrderEnterpriseDto order : orderList) {
            saveCarsMileage(collect.get(order.getOrderCode()), order, currentMileage);
        }
    }

    @Override
    public void updateMileageMonitoring() {
        List<CarsMileageMonitoringEnterpriseResDto> dto = monitoringEnterpriseService.listMileageUnMonitoring();
        if (CollectionUtils.isEmpty(dto)) {
            return;
        }
        List<String> vinList = dto.stream().map(CarsMileageMonitoringEnterpriseResDto::getVin).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(vinList)) {
            return;
        }
        Map<String, Integer> currentMileage = new HashMap<>();
        try {
            currentMileage = iovCarService.getOdoMileage(vinList);
        } catch (Exception e) {
            log.info("获取车联网实际里程失败-入参：{}", vinList);
            return;
        }
        if (CollectionUtils.isEmpty(currentMileage)) {
            return;
        }

        for (CarsMileageMonitoringEnterpriseResDto resDto : dto) {

            Integer mileage = currentMileage.get(resDto.getVin());
            if (mileage != null) {
                CarsMileageMonitoringEnterpriseDto dto1 = new CarsMileageMonitoringEnterpriseDto();
                dto1.setId(resDto.getId());
                //止期里程
                dto1.setEndMileage(mileage);
                //行驶里程
                dto1.setDriveMileage(mileage - resDto.getStartMileage());
                dto1.setGmtModified(LocalDateTime.now());
                carsMileageMonitoringBizService.updateCarsMileage(dto1);
            }
        }

    }

    @Override
    public void generateAbnormalDataMileageMonitoring() {
        Map<String, String> stringStringMap = redisUtil.hgetAll(RedisConstants.MILEAGE_MONITORING_EXCEPTION_DATE_KEY);
        log.info("redis未生成报警的数据:{}",stringStringMap);
        if (CollectionUtils.isEmpty(stringStringMap)) {
            return;
        }
        for (String value : stringStringMap.values()) {
            LocalDate parse = LocalDate.parse(value);
            generateMonitoring(parse);
            redisUtil.hdel(RedisConstants.MILEAGE_MONITORING_EXCEPTION_DATE_KEY, value);
        }
    }

    /**
     * 判断时候存在已生成的订单
     */
    public CarsMileageMonitoringEnterpriseDto getCarsMileageBy(Long order) {
        return monitoringEnterpriseService.getMileageMonitoringEnterprise(order);
    }

    /**
     * 根据车辆订单生成报警
     *
     * @param dto            the dto  企业订单车辆dto
     * @param enterpriseDto  the enterprise dto 企业订单dto
     * @param currentMileage the current mileage  当前里程
     * @author wanghualin
     */
    public void saveCarsMileage(EnterpriseCarDto dto, OrderEnterpriseDto enterpriseDto, Map<String, Integer> currentMileage) {
        CarsMileageMonitoringEnterpriseDto monitoring = new CarsMileageMonitoringEnterpriseDto();
        CarsMileageMonitoringEnterpriseDto carsMileageBy = getCarsMileageBy(dto.getOrderCode());
        monitoring.setOrderCode(dto.getOrderCode());
        monitoring.setCarId(dto.getCarId());
        monitoring.setVin(dto.getVin());
        monitoring.setEnterpriseId(enterpriseDto.getEnterpriseId());
        monitoring.setMileageUpper(dto.getMileageUpper());
        //判断是不是第一次处
        if (carsMileageBy == null) {
            monitoring.setStartMileage(dto.getStartMileage());
            monitoring.setStartTime(enterpriseDto.getLeaseInception());
            int dayOfMonth = enterpriseDto.getLeaseInception().getDayOfMonth();
            if (dayOfMonth > DAY_OF_MONTHS_CRITICAL) {
                monitoring.setEndTime(enterpriseDto.getLeaseInception().plusMonths(2).withDayOfMonth(1));
            } else {
                monitoring.setEndTime(enterpriseDto.getLeaseInception().plusMonths(1));
            }
        } else {
            monitoring.setStartMileage(carsMileageBy.getEndMileage());
            monitoring.setStartTime(carsMileageBy.getEndTime());
            monitoring.setEndTime(carsMileageBy.getEndTime().plusMonths(1));
        }
        Integer mileage = null;
        if (!CollectionUtils.isEmpty(currentMileage)) {
            mileage = currentMileage.get(dto.getVin());
        }
        if (mileage != null) {
            //止期里程
            monitoring.setEndMileage(mileage);
            //行驶里程
            monitoring.setDriveMileage(mileage - monitoring.getStartMileage());
        }
        monitoring.setGmtCreate(LocalDateTime.now());
        carsMileageMonitoringBizService.saveCarsMileage(monitoring);
    }


    /**
     * 起租日为29、30、31日为，获取时间顺延至1日23：59：59执行里程监控
     *
     * @param localDate
     * @return
     */
    public List<Integer> getDayOfMonths(LocalDate localDate) {
        List<Integer> days = new ArrayList<>();
        int day = localDate.getDayOfMonth();
        if (day == 1) {
            days.add(29);
            days.add(30);
            days.add(31);
            days.add(1);
            //得到当月最后天
        } else if (day > 1 && day <= DAY_OF_MONTHS_CRITICAL) {
            days.add(day);
        }
        return days;
    }


    public static void main(String[] args) {
      LocalDate localDate=LocalDate.now();
        System.out.println(localDate);
    }
}
